home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / shutdown.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  10.6 KB  |  491 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: shutdown.c,v 5.2 1992/11/11 22:09:08 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <netdb.h>
  13. #include <pwd.h>
  14. #include <string.h>
  15. #include <syslog.h>
  16.  
  17. #include "sio.h"
  18. #include "str.h"
  19.  
  20. #include "defs.h"
  21.  
  22. char *malloc() ;
  23. char *crypt() ;
  24.  
  25. void msg() ;
  26.  
  27. typedef enum { SD_LOGIN, SD_SHELL, SD_EXEC, SD_FINGER } shutdown_e ;
  28.  
  29. struct shutdown_function
  30. {
  31.     char *service_name ;
  32.     voidfunc shutdown ;
  33.     char *function_name ;
  34.     shutdown_e sd_id ;
  35. } ;
  36.  
  37.  
  38. typedef enum
  39.     {
  40.         RS_EOF, RS_IOERR, RS_NOMEM, RS_OK, RS_TOOLONG, RS_BADCONN
  41.     } read_status_e ;
  42.  
  43. void rlogin_shutdown() ;
  44. void rexec_shutdown() ;
  45. void rsh_shutdown() ;
  46. void finger_shutdown() ;
  47.  
  48. static struct shutdown_function shutdown_functions[] =
  49.    {
  50.       { "login",        rlogin_shutdown,    "rlogin_shutdown",    SD_LOGIN     },
  51.         { "shell",        rsh_shutdown,        "rsh_shutdown",        SD_SHELL        },
  52.         { "exec",        rexec_shutdown,    "rexec_shutdown",        SD_EXEC        },
  53.         { "finger",        finger_shutdown,    "finger_shutdown",    SD_FINGER    },
  54.       { CHAR_NULL }
  55.    } ;
  56.  
  57.  
  58. /*
  59.  * NOTE: All shutdown functions assume that the process will exit
  60.  *         very soon, so they don't bother to deallocate any malloc'ed
  61.  *            memory. In particular, it is not guaranteed that the memory 
  62.  *            returned by these functions will point to malloc'ed memory
  63.  */
  64.  
  65.  
  66. /*
  67.  * Locate and return the shutdown function for the given service
  68.  */
  69. voidfunc get_shutdown_by_name( service ) 
  70.     register char *service ;
  71. {
  72.     register struct shutdown_function *sfp ;
  73.  
  74.     for ( sfp = &shutdown_functions[ 0 ] ; sfp->service_name ; sfp++ )
  75.         if ( EQ( service, sfp->service_name ) )
  76.             return( sfp->shutdown ) ;
  77.     return( NULL ) ;
  78. }
  79.  
  80.  
  81. char *get_shutdown_by_addr( func )
  82.     register voidfunc func ;
  83. {
  84.     register struct shutdown_function *sfp ;
  85.  
  86.     for ( sfp = &shutdown_functions[ 0 ] ; sfp->service_name ; sfp++ )
  87.         if ( func == sfp->shutdown )
  88.             break ;
  89.     return( sfp->function_name ) ;
  90. }
  91.  
  92.  
  93. /*
  94.  * Returns a string that explains the given status
  95.  */
  96. PRIVATE char *rs_explain( status )
  97.     register read_status_e status ;
  98. {
  99.     register char *str ;
  100.  
  101.     if ( status == RS_NOMEM )
  102.         str = "Error: out of memory" ;
  103.     else if ( status == RS_TOOLONG )
  104.         str = "input too long" ;
  105.     else if ( status == RS_IOERR )
  106.         str = "Error: I/O" ;
  107.     else if ( status == RS_EOF )
  108.         str = "Error: end-of-file" ;
  109.     else if ( status == RS_BADCONN )
  110.         str = "Error: bad connection" ;
  111.     else
  112.         str = "Error: unknown" ;
  113.     return( str ) ;
  114. }
  115.  
  116.  
  117. /*
  118.  * Read a string of length at most maxlen from socket sd
  119.  * The string is placed in buf (if buf is not NULL). If buf
  120.  * is NULL, the input is drained.
  121.  * The input string is always read even if the allowed length
  122.  * is exceeded (the extra characters are ignored).
  123.  * max_len is the maximum length of the input string excluding the
  124.  * terminating NUL.
  125.  * The actual length is returned in lenp.
  126.  */
  127. PRIVATE read_status_e read_string( sd, max_len, buf, lenp )
  128.     int sd ;
  129.     register unsigned max_len ;
  130.     char *buf ;
  131.     unsigned *lenp ;
  132. {
  133.     register status_e status = OK ;
  134.     register int len = 0 ;
  135.     char c ;
  136.     register char *p ;
  137.     int cc ;
  138.     read_status_e read_status ;
  139.     int drain_input = ( buf == NULL ) ;
  140.  
  141.     if ( drain_input )
  142.     {
  143.         status = FAILED ;
  144.         p = &c ;
  145.     }
  146.     else
  147.     {
  148.         p = buf ;
  149.         status = OK ;
  150.     }
  151.  
  152.     for ( ;; )
  153.     {
  154.         /*
  155.          * Keep reading characters one by one (ugly !!!)
  156.          * If status == FAILED, don't store them
  157.          * Interesting side-effect: since we stop increasing p in
  158.          * this case, *p will be used for storing all subsequent input
  159.          * until the NUL. So we get a NUL terminated string with
  160.          * the extra characters ignored.
  161.          */
  162.         if ( len > max_len )
  163.         {
  164.             status = FAILED ;
  165.             read_status = RS_TOOLONG ;
  166.         }
  167.  
  168.         /*
  169.          * If an I/O error occurs, end the loop
  170.          */
  171.         if ( ( cc = read( sd, p, 1 ) ) != 1 )
  172.         {
  173.             if ( cc == -1 )
  174.                 if ( errno == EINTR )
  175.                     continue ;
  176.                 else
  177.                     read_status = RS_IOERR ;
  178.             else
  179.                 read_status = RS_EOF ;
  180.             status = FAILED ;
  181.             break ;
  182.         }
  183.         if ( *p == NUL )
  184.             break ;
  185.         if ( status == OK )
  186.         {
  187.             len++ ;
  188.             p++ ;
  189.         }
  190.     }
  191.     if ( status == OK )
  192.     {
  193.         *lenp = len ;
  194.         read_status = RS_OK ;
  195.     }
  196.     return( drain_input ? RS_OK : read_status ) ;
  197. }
  198.  
  199.  
  200. /*
  201.  * Allocates a single buffer big enough to hold <count> strings whose
  202.  * maximum lengths are given in the <limits> array
  203.  * The pointers in the <strings> array will point to the part
  204.  * of the buffer for each string.
  205.  */
  206. PRIVATE char *setup( count, limits, strings )
  207.     register unsigned count ;
  208.     unsigned limits[] ;
  209.     char *strings[] ;
  210. {
  211.     register unsigned total_len ;
  212.     register unsigned index ;
  213.     register unsigned u ;
  214.     char *buf ;
  215.  
  216.     for ( u = 0, total_len = 0 ; u < count ; u++ )
  217.         total_len += limits[ u ] ;
  218.     
  219.     buf = malloc( total_len + count ) ;        /* count the NULs */
  220.     if ( buf == NUL )
  221.         return( NULL ) ;
  222.     
  223.     for ( u = 0, index = 0 ; u < count ; u++ )
  224.     {
  225.         strings[ u ] = &buf[ index ] ;
  226.         index += limits[ u ] + 1 ;
  227.     }
  228.     return( buf ) ;
  229. }
  230.  
  231.  
  232.  
  233. PRIVATE status_e rservices_common( id, sd, nargs, 
  234.                                         limits, strings, total_lenp, pp )
  235.     shutdown_e id ;                /* service id                                             */
  236.     unsigned nargs ;                /* number of expected args. args are             */
  237.                                         /* nul-terminated strings                            */
  238.     unsigned limits[] ;            /* max length of each arg                            */
  239.     char *strings[] ;                /* array of arg pointers                            */
  240.     unsigned *total_lenp ;        /* total length of args                                */
  241.     char **pp ;                        /* pointer to string to put error message        */
  242. {
  243.     read_status_e rs ;
  244.     char *store_buf ;
  245.     unsigned total_len ;
  246.     unsigned len ;
  247.     int i ;
  248.     char *func = "rservices_common" ;
  249.  
  250.     store_buf = setup( nargs, limits, strings ) ;
  251.     if ( store_buf == NULL )
  252.     {
  253.         *pp = rs_explain( RS_NOMEM ) ;
  254.         return( FAILED ) ;
  255.     }
  256.  
  257.     for ( i = 0, total_len = 0 ; i < nargs ; i++ )
  258.     {
  259.         rs = read_string( sd, limits[ i ], strings[ i ], &len ) ;
  260.         if ( rs != RS_OK )
  261.         {
  262.             *pp = rs_explain( rs ) ;
  263.             return( FAILED ) ;
  264.         }
  265.  
  266.         if ( i == 0 && ( id == SD_SHELL || id == SD_EXEC ) )
  267.         {
  268.             unsigned short port = atoi( strings[ 0 ] ) ;
  269.  
  270.             if ( debug.on )
  271.                 msg( LOG_DEBUG, func, "port for new connection = %d", port ) ;
  272.  
  273.             if ( port != 0 && connect_back( id, sd, port ) == -1 )
  274.             {
  275.                 *pp = rs_explain( RS_BADCONN ) ;
  276.                 return( FAILED ) ;
  277.             }
  278.         }
  279.         else
  280.             total_len += len ;
  281.     }
  282.     *total_lenp = total_len ;
  283.     return( OK ) ;
  284. }
  285.  
  286.  
  287. PRIVATE int connect_back( id, sd, port )
  288.     shutdown_e id ;
  289.     int sd ;
  290.     unsigned short port ;
  291. {
  292.     struct sockaddr_in sin ;
  293.     int sin_len = sizeof( sin ) ;
  294.     int new_sd ;
  295.     char *func = "connect_back" ;
  296.  
  297.     /*
  298.      * Get the remote address
  299.      */
  300.     if ( getpeername( sd, SA( &sin ), &sin_len ) == -1 )
  301.     {
  302.         if ( debug.on )
  303.             msg( LOG_DEBUG, func, "id=%d, getpeername: %m", (int) id ) ;
  304.         return( -1 ) ;
  305.     }
  306.  
  307.     /*
  308.      * Get a socket for the new connection.
  309.      * For the shell service, the socket must have a proviliged local port
  310.      */
  311.     if ( id == SD_SHELL )
  312.     {
  313.         int local_port = IPPORT_RESERVED - 1 ;
  314.         unsigned short client_port = ntohs( sin.sin_port ) ;
  315.  
  316.         if ( ! ( client_port >= IPPORT_RESERVED/2 &&
  317.                                             client_port < IPPORT_RESERVED ) )
  318.         return( -1 ) ;
  319.  
  320.         if ( ( new_sd = rresvport( &local_port ) ) == -1 )
  321.             return( -1 ) ;
  322.     }
  323.     else if ( id == SD_EXEC )
  324.     {
  325.         if ( ( new_sd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
  326.             return( -1 ) ;
  327.     }
  328.     else
  329.         return( -1 ) ;
  330.  
  331.     sin.sin_port = htons( port ) ;
  332.     sin.sin_family = AF_INET ;
  333.     if ( connect( new_sd, SA( &sin ), sizeof( sin ) ) == -1 )
  334.     {
  335.         if ( debug.on )
  336.             msg( LOG_DEBUG, func, "connect: %m (port=%d)", port ) ;
  337.         (void) close( new_sd ) ;
  338.         return( -1 ) ;
  339.     }
  340.     return( new_sd ) ;
  341. }
  342.  
  343.  
  344. #define RLOGIN_ARGS         4
  345.  
  346. PRIVATE void rlogin_shutdown( sd, pp )
  347.     int sd ;
  348.     char **pp ;
  349. {
  350.     char *print_buf ;
  351.     unsigned print_buf_size ;
  352.     unsigned total_len ;
  353.     char *strings[ RLOGIN_ARGS ] ;
  354.     static unsigned limits[ RLOGIN_ARGS ] = { 0, 16, 16, 4096 } ;
  355.  
  356.     (void) write( sd, "", 1 ) ;
  357.  
  358.     if ( pp == NULL )
  359.         return ;
  360.  
  361.     if ( rservices_common( SD_LOGIN, sd,
  362.                 RLOGIN_ARGS, limits, strings, &total_len, pp ) == FAILED )
  363.         return ;
  364.  
  365.     print_buf_size = total_len + 100 ;
  366.     print_buf = malloc( print_buf_size ) ;
  367.     if ( print_buf != NULL )
  368.         *pp = strx_sprint( print_buf, print_buf_size,
  369.                         "remote_user=%s local_user=%s tty=%s",
  370.                             strings[ 1 ], strings[ 2 ], strings[ 3 ] ) ;
  371.     else
  372.         *pp = rs_explain( RS_NOMEM ) ;
  373. }
  374.  
  375.  
  376.     
  377. #define REXEC_ARGS            4
  378. #define SALT_LEN                2
  379. #define VERIFY_LEN            40
  380.  
  381. PRIVATE void rexec_shutdown( sd, pp )
  382.     int sd ;
  383.     char **pp ;
  384. {
  385.     char *print_buf ;
  386.     unsigned print_buf_size ;
  387.     char *password ;
  388.     char salt[ SALT_LEN ] ;
  389.     struct passwd *pw ;
  390.     char *verify ;
  391.     unsigned total_len ;
  392.     char error_indication = '\1' ;
  393.     char *error_message = "Permission denied.\n" ;
  394.     char *strings[ REXEC_ARGS ] ;
  395.     static unsigned limits[ REXEC_ARGS ] = { 5, 16, 16, 4096 } ;
  396.  
  397.     (void) write( sd, &error_indication, 1 ) ;
  398.     (void) write( sd, error_message, strlen( error_message ) + 1 ) ;
  399.     
  400.     if ( pp == NULL )
  401.         return ;
  402.  
  403.     if ( rservices_common( SD_EXEC, sd,
  404.                 REXEC_ARGS, limits, strings, &total_len, pp ) == FAILED )
  405.         return ;
  406.  
  407.     /*
  408.      * Verify the password
  409.      */
  410.     password = strings[ 2 ] ;
  411.     pw = getpwnam( strings[ 1 ] ) ;
  412.     if ( pw != NULL )
  413.     {
  414.         strncpy( salt, pw->pw_passwd, SALT_LEN )[ SALT_LEN ] = NUL ;
  415.         if ( EQ( crypt( password, salt ), pw->pw_passwd ) )
  416.             verify = "ok" ;
  417.         else
  418.             verify = "failed" ;
  419.     }
  420.     else
  421.         verify = "baduser" ;
  422.  
  423.     str_fill( password, ' ' ) ;        /* clear the password */
  424.  
  425.     print_buf_size = total_len + 100 ;
  426.     print_buf = malloc( print_buf_size ) ;
  427.     if ( print_buf != NULL )
  428.         *pp = strx_sprint( print_buf, print_buf_size, 
  429.                             "remote_user=%s verify=%s command=%s",
  430.                                             strings[ 1 ], verify, strings[ 3 ] ) ;
  431.     else
  432.         *pp = rs_explain( RS_NOMEM ) ;
  433. }
  434.  
  435.  
  436.  
  437. #define RSH_ARGS            4
  438.  
  439. PRIVATE void rsh_shutdown( sd, pp )
  440.     int sd ;
  441.     char **pp ;
  442. {
  443.     char *print_buf ;
  444.     unsigned print_buf_size ;
  445.     unsigned total_len ;
  446.     char error_indication = '\1' ;
  447.     char *error_message = "Permission denied.\n" ;
  448.     char *strings[ RSH_ARGS ] ;
  449.     static unsigned limits[ RSH_ARGS ] = { 5, 16, 16, 4096 } ;
  450.  
  451.     (void) write( sd, &error_indication, 1 ) ;
  452.     (void) write( sd, error_message, strlen( error_message ) + 1 ) ;
  453.  
  454.     if ( pp == NULL )
  455.         return ;
  456.     
  457.     if ( rservices_common( SD_SHELL, sd,
  458.                     RSH_ARGS, limits, strings, &total_len, pp ) == FAILED )
  459.         return ;
  460.     
  461.     print_buf_size = total_len + 100 ;
  462.     print_buf = malloc( print_buf_size ) ;
  463.     if ( print_buf != NULL )
  464.         *pp = strx_sprint( print_buf, print_buf_size,
  465.                     "remote_user=%s local_user=%s command=%s",
  466.                             strings[ 1 ], strings[ 2 ], strings[ 3 ] ) ;
  467.     else
  468.         *pp = rs_explain( RS_NOMEM ) ;
  469. }
  470.  
  471.  
  472. PRIVATE void finger_shutdown( sd, pp )
  473.     int sd ;
  474.     char **pp ;
  475. {
  476.     char *line ;
  477.     int line_len ;
  478.  
  479.     if ( pp == NULL )
  480.         return ;
  481.     
  482.     line = Srdline( sd ) ;
  483.     line_len = SIOLINELEN( sd ) ;
  484.  
  485.     if ( line_len > 0 && line[ line_len-1 ] == '\r' )
  486.         line[ --line_len ] = NULL ;
  487.  
  488.     *pp = ( line_len == 0 ) ? "EMPTY-LINE" : line ;
  489. }
  490.  
  491.